package com.wing.productionPlan.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wing.common.exception.BusinessException;
import com.wing.common.utils.CodeUtil;
import com.wing.common.utils.DateUtils;
import com.wing.enterprise.product.model.entity.ResBenchmarkBookEchnology;
import com.wing.productionPlan.dao.DynamicDao;
import com.wing.productionPlan.dao.ProductionPieceRateDao;
import com.wing.productionPlan.dao.ProductionTheWorkOrderDao;
import com.wing.productionPlan.enumeration.PieceRateDetailStatusEnum;
import com.wing.productionPlan.enumeration.PieceRateStatusEnum;
import com.wing.productionPlan.model.entity.ProductionPieceRate;
import com.wing.productionPlan.model.entity.ProductionPieceRateDetail;
import com.wing.productionPlan.model.entity.ProductionTheWorkOrder;
import com.wing.productionPlan.model.request.ProductionPieceRateForm;
import com.wing.productionPlan.model.response.ProductionPieceRateDetailVO;
import com.wing.productionPlan.model.response.ProductionPieceRateVO;
import com.wing.qualityTesting.model.entity.WorkOrderQualityTestingTask;
import com.wing.qualityTesting.service.WorkOrderQualityTestingTaskService;
import com.wing.web.utils.AddUpdateUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * 计件工资单-ServiceImpl
 *
 * @author
 */
@Service
@Slf4j
public class ProductionPieceRateServiceImpl extends ServiceImpl<ProductionPieceRateDao, ProductionPieceRate> implements ProductionPieceRateService {

    @Autowired
    private DynamicDao dynamicDao;
    @Autowired
    private ProductionPieceRateDetailService pieceRateDetailService;
    @Autowired
    private WorkOrderQualityTestingTaskService qualityTestingTaskService;
    @Autowired
    private ProductionPieceRateDao pieceRateDao;
    @Autowired
    private ProductionTheWorkOrderDao theWorkOrderDao;
    @Autowired
    private ProductionTheWorkOrderService theWorkOrderService;
    
    @Override
    public int add(ProductionPieceRateForm productionPieceRateForm) {
        //校验
        ProductionPieceRate productionPieceRate =new ProductionPieceRate();
        CopyOptions copyOptions = CopyOptions.create()
            .setEditable(ProductionPieceRate.class)
            .setIgnoreError(true)
            .setIgnoreNullValue(true);
        BeanUtil.copyProperties(productionPieceRateForm, productionPieceRate, copyOptions);
        //编号及相关信息
        String today = DateUtil.format(new Date(), DateUtils.DATE_PATTERN_FORMAT);
        String thisMonth = DateUtil.format(new Date(), DateUtils.DATE_PATTERN_FORMAT_MONTH2);
        Integer maxNo = dynamicDao.getDayMaxNo("ord_production_piece_rate");
        String code = CodeUtil.getCode(maxNo);
        productionPieceRate.setCode("JJGZ" + thisMonth + code);
        productionPieceRate.setNo(Integer.valueOf(code));
        productionPieceRate.setDay(Integer.valueOf(today));
        productionPieceRate.setMonth(Integer.valueOf(thisMonth));
        AddUpdateUtil.fillInsertInfo(productionPieceRate);
        int count = baseMapper.insert(productionPieceRate);
        productionPieceRateForm.setId(productionPieceRate.getId());
        return count;
    }

    @Override
    public List<ProductionPieceRateVO> list4app(Map<String, Object> params) {
        return baseMapper.list4app(params);
    }

    @Override
    public Page<ProductionPieceRateVO> pageList4app(Page page, Map<String, Object> params) {
        List<ProductionPieceRateVO> list = baseMapper.list4app(page, params);
        page.setRecords(list);
        return page;
    }

    @Override
    public ProductionPieceRateVO get4appById(Long id) {
        return baseMapper.get4appById(id);
    }

    @Override
    public int create() {
        AtomicInteger updateCount = new AtomicInteger(0);
        Map<String, Object> params = new HashMap<>();
//        params.put("lastMonth", 1);//上一个月
        params.put("status", 1);//已确认
        List<ProductionPieceRateDetailVO> pieceRateDetailListAll = pieceRateDetailService.list4app(params);
        if (CollectionUtil.isNotEmpty(pieceRateDetailListAll)) {
            Map<Long, List<ProductionPieceRateDetailVO>> prDetailGbTwoPeople = pieceRateDetailListAll.stream().collect(Collectors.groupingBy(ProductionPieceRateDetailVO::getTheWorkOrderPeople));
            prDetailGbTwoPeople.forEach((key, pieceRateDetailList) -> {
                ProductionPieceRateForm pieceRateForm = new ProductionPieceRateForm();
                pieceRateForm.setTheWorkOrderPeople(key);
                pieceRateForm.setTheWorkOrderPeopleName(pieceRateDetailList.get(0).getTheWorkOrderPeopleName());
                pieceRateForm.setWorkQuantity(pieceRateDetailList.size());
                pieceRateForm.setQualifiedSalary(pieceRateDetailList.stream().map(p -> p.getOkSalary()).reduce(BigDecimal.ZERO, BigDecimal::add));
                pieceRateForm.setUnqualifiedSalary(pieceRateDetailList.stream().map(p -> p.getQualifiedNoSalary()).reduce(BigDecimal.ZERO, BigDecimal::add));
                //计算报废罚款
                List<Long> theWorkOrderIdList = pieceRateDetailList.stream().map(o -> o.getTheWorkOrderId()).collect(Collectors.toList());
                AtomicReference<BigDecimal> scrapPenaltySum = new AtomicReference<>(BigDecimal.ZERO);
                theWorkOrderIdList.stream().forEach(id -> {
                    //质检任务获取报废数
                    QueryWrapper<WorkOrderQualityTestingTask> qualityTestingTaskQueryWrapper = new QueryWrapper<>();
                    qualityTestingTaskQueryWrapper.eq("report_order_id", id);
                    List<WorkOrderQualityTestingTask> qualityTestingTaskList = qualityTestingTaskService.list(qualityTestingTaskQueryWrapper);
                    if (CollectionUtil.isNotEmpty(qualityTestingTaskList)) {
                        BigDecimal scrapPenalty;
                        //基准书获取报废定额
                        ResBenchmarkBookEchnology benchBookEch = theWorkOrderDao.getBenchBookEchByTheWorkOrderId(id);
                        if (ObjectUtil.isNotNull(benchBookEch)) {
                            Integer ngQuantitySum = qualityTestingTaskList
                                .stream().map(o -> o.getNgQuantity())
                                .mapToInt(Integer::intValue)
                                .sum();//报废数
                            BigDecimal ngSalaryQuota = ObjectUtil.isNull(benchBookEch.getNgSalaryQuota()) ? BigDecimal.ZERO : benchBookEch.getNgSalaryQuota();//报废定额
                            scrapPenalty = BigDecimal.valueOf(ngQuantitySum).multiply(ngSalaryQuota);//报废罚款
                            scrapPenaltySum.updateAndGet(v -> v.add(scrapPenalty));//报废罚款-总
                        }
                    }
                });
                pieceRateForm.setScrapPenalty(scrapPenaltySum.get());//报废罚款
                pieceRateForm.setPieceRateAmount(pieceRateForm.getQualifiedSalary().add(pieceRateForm.getUnqualifiedSalary()));
                pieceRateForm.setStatus(PieceRateStatusEnum.TO_CONFIRM.getCode());
                updateCount.addAndGet(add(pieceRateForm));
                //将计件工资id挂到明细上
                if (updateCount.get() > 0) {
                    pieceRateDetailList.stream().forEach(p-> {
                        ProductionPieceRateDetail pieceRateDetail = new ProductionPieceRateDetail();
                        pieceRateDetail.setId(p.getId());
                        pieceRateDetail.setPieceRateId(pieceRateForm.getId());
                        pieceRateDetailService.updateById(pieceRateDetail);
                    });
                }
            });
        }
        return updateCount.get();
    }

    @Override
    public void create2(Long theWorkOrderPeople) {
        Map<String, Object> params = new HashMap<>();
//        params.put("lastMonth", 1);//上一个月
        params.put("month", Integer.valueOf(DateUtil.format(new Date(), DateUtils.DATE_PATTERN_FORMAT_MONTH2)));//本月，即点确认时的月份
        params.put("status", PieceRateDetailStatusEnum.CONFIRMED.getCode());//已确认
        params.put("the_work_order_people", theWorkOrderPeople);//报工人
        List<ProductionPieceRateDetailVO> pieceRateDetailList = pieceRateDetailService.list4app(params);
        if (CollectionUtil.isNotEmpty(pieceRateDetailList)) {
            ProductionPieceRateForm pieceRateForm = new ProductionPieceRateForm();
            pieceRateForm.setTheWorkOrderPeople(pieceRateDetailList.get(0).getTheWorkOrderPeople());
            pieceRateForm.setTheWorkOrderPeopleName(pieceRateDetailList.get(0).getTheWorkOrderPeopleName());
            pieceRateForm.setWorkQuantity(pieceRateDetailList.size());
            pieceRateForm.setQualifiedSalary(pieceRateDetailList.stream().map(p -> p.getOkSalary()).reduce(BigDecimal.ZERO, BigDecimal::add));
            pieceRateForm.setUnqualifiedSalary(pieceRateDetailList.stream().map(p -> p.getQualifiedNoSalary()).reduce(BigDecimal.ZERO, BigDecimal::add));
            //计算报废罚款
            List<Long> theWorkOrderIdList = pieceRateDetailList.stream().map(o -> o.getTheWorkOrderId()).collect(Collectors.toList());
            AtomicReference<BigDecimal> scrapPenaltySum = new AtomicReference<>(BigDecimal.ZERO);
            theWorkOrderIdList.stream().forEach(id -> {
                //质检任务获取报废数
                QueryWrapper<WorkOrderQualityTestingTask> qualityTestingTaskQueryWrapper = new QueryWrapper<>();
                qualityTestingTaskQueryWrapper.eq("report_order_id", id);
                List<WorkOrderQualityTestingTask> qualityTestingTaskList = qualityTestingTaskService.list(qualityTestingTaskQueryWrapper);
                if (CollectionUtil.isEmpty(qualityTestingTaskList)) {
                    throw new BusinessException("质检任务不存在");
                }
                BigDecimal scrapPenalty;
                //基准书获取报废定额
                ResBenchmarkBookEchnology benchBookEch = theWorkOrderDao.getBenchBookEchByTheWorkOrderId(id);
                if (ObjectUtil.isNotNull(benchBookEch)) {
                    Integer ngQuantitySum = qualityTestingTaskList
                        .stream().map(o -> ObjectUtil.isNull(o.getNgQuantity()) ? 0 : o.getNgQuantity())
                        .mapToInt(Integer::intValue)
                        .sum();//报废数
                    BigDecimal ngSalaryQuota = ObjectUtil.isNull(benchBookEch.getNgSalaryQuota()) ? BigDecimal.ZERO : benchBookEch.getNgSalaryQuota();//报废定额
                    scrapPenalty = BigDecimal.valueOf(ngQuantitySum).multiply(ngSalaryQuota);//报废罚款
                    scrapPenaltySum.updateAndGet(v -> v.add(scrapPenalty));//报废罚款-总
                }
            });
            pieceRateForm.setScrapPenalty(scrapPenaltySum.get());//报废罚款
            pieceRateForm.setPieceRateAmount(pieceRateForm.getQualifiedSalary().add(pieceRateForm.getUnqualifiedSalary()));
            pieceRateForm.setStatus(PieceRateStatusEnum.TO_CONFIRM.getCode());
            //判断是否已生成计件工资单
            ProductionPieceRateDetailVO first = pieceRateDetailList.stream().filter(p -> ObjectUtil.isNotNull(p.getPieceRateId())).findFirst().orElse(null);
            //未生成的新增，已生成的更新
            if (ObjectUtil.isNull(first)) {
                add(pieceRateForm);
                //将计件工资id挂到明细上
                pieceRateDetailList.stream().forEach(p -> {
                    ProductionPieceRateDetail pieceRateDetail = new ProductionPieceRateDetail();
                    pieceRateDetail.setId(p.getId());
                    pieceRateDetail.setPieceRateId(pieceRateForm.getId());
                    pieceRateDetailService.updateById(pieceRateDetail);
                });
            } else {
                ProductionPieceRate pieceRate = new ProductionPieceRate();
                BeanUtil.copyProperties(pieceRateForm, pieceRate, CopyOptions.create().setIgnoreNullValue(true));
                pieceRate.setId(first.getPieceRateId());
                updateById(pieceRate);
            }
        }
    }
    
    @Override
    public Boolean audit(Long id, String status) {
        ProductionPieceRate productionPieceRate = baseMapper.selectById(id);
        if (ObjectUtil.isNull(productionPieceRate)) {
            throw new BusinessException("单据不存在！");
        }
        Integer pieceRateStatus = productionPieceRate.getStatus();
        ProductionPieceRate pieceRateUpdate = new ProductionPieceRate();
        UpdateWrapper<ProductionPieceRateDetail> pieceRateDetailUpdate = new UpdateWrapper<>();
        UpdateWrapper<ProductionTheWorkOrder> theWorkOrderUpdate = new UpdateWrapper<>();
        switch (status) {
            case "confirm":
                if (PieceRateStatusEnum.TO_CONFIRM.equals(pieceRateStatus)) {
                    throw new BusinessException("待确认状态才能确认！");
                }
                pieceRateUpdate.setStatus(PieceRateStatusEnum.CONFIRMED.getCode());
                pieceRateDetailUpdate.set("status", PieceRateDetailStatusEnum.CONFIRMED.getCode());
                theWorkOrderUpdate.set("status", ProductionTheWorkOrder.Status.pieceRateConfirmed);
                break;
            case "audit":
                if (PieceRateStatusEnum.CONFIRMED.equals(pieceRateStatus)) {
                    throw new BusinessException("已确认状态才能审核！");
                }
                pieceRateUpdate.setStatus(PieceRateStatusEnum.TO_SETTLEMENT.getCode());
                pieceRateDetailUpdate.set("status", PieceRateDetailStatusEnum.TO_SETTLEMENT.getCode());
                theWorkOrderUpdate.set("status", ProductionTheWorkOrder.Status.toSettle);
                break;
            case "settle":
                if (PieceRateStatusEnum.SETTLEMENTED.equals(pieceRateStatus)) {
                    throw new BusinessException("待结算状态才能结算！");
                }
                pieceRateUpdate.setStatus(PieceRateStatusEnum.SETTLEMENTED.getCode());
                pieceRateDetailUpdate.set("status", PieceRateDetailStatusEnum.SETTLEMENTED.getCode());
                theWorkOrderUpdate.set("status", ProductionTheWorkOrder.Status.settled);
                break;
        }
        //更新计件工资
        pieceRateUpdate.setId(id);
        int count = baseMapper.updateById(pieceRateUpdate);
        if (count > 0) {
            //更新计件工资明细
            pieceRateDetailUpdate.eq("piece_rate_id", id);
            pieceRateDetailService.update(pieceRateDetailUpdate);
            //更新报工单
            QueryWrapper<ProductionPieceRateDetail> pieceRateDetailQueryWrapper = new QueryWrapper<>();
            pieceRateDetailQueryWrapper.eq("piece_rate_id", id);
            List<ProductionPieceRateDetail> pieceRateDetail = pieceRateDetailService.list(pieceRateDetailQueryWrapper);
            List<Long> theWorkOrderIdList = pieceRateDetail.stream().map(p -> p.getTheWorkOrderId()).collect(Collectors.toList());
            theWorkOrderUpdate.in("id", theWorkOrderIdList);
            theWorkOrderService.update(theWorkOrderUpdate);
        }
        return count > 0;
    }


}
